import { Injectable, Injector } from '@angular/core'
import { Router } from '@angular/router'
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpErrorResponse,
  HttpEvent,
  HttpResponseBase,
  HttpClient,
  HttpHeaders,
  HttpResponse
} from '@angular/common/http'
import { Observable, of, throwError, Observer } from 'rxjs'
import { mergeMap, catchError, retryWhen, delay, tap, switchMap } from 'rxjs/operators'
import { Store } from '@ngxs/store'
import { StatusTransformer } from '../http/transformers/status.transformer'

const CODEMESSAGE = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。'
}

/**
 * 默认HTTP拦截器
 */
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
  constructor(
    private injector: Injector,
    private http: HttpClient,
    private store: Store,
    private statusTransformer: StatusTransformer
  ) {}

  // 对应错误码处理函数
  private readonly errorHandlerMapping = {
    403: this.forbiddenErrorHandle,
    500: this.serverErrorHandle
  }

  public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      tap((response: HttpResponse<any>) => {
        if (response instanceof HttpResponse) {
          if (!this.statusTransformer.transform(response.body)) {
            const [error] = response.body.ret
            throw error
          }
        }
      }),
      catchError((error: HttpErrorResponse) => {
        // 获取对应错误处理函数
        const errorHandler = (this.errorHandlerMapping[error.status] || this.defaultErrorHandle).bind(this)
        // 获取错误处理返回结果
        const result = errorHandler(error)
        // 打印错误信息
        console.group('HTTP REQUEST ERROR')
        console.error(req.url)
        console.error(error)
        console.groupEnd()
        // 抛出错误异常
        return throwError(result || error.message || error.statusText)
      })
    )
  }

  /**
   * 500异常处理
   * @param error
   */
  private serverErrorHandle(error) {
    return error
  }

  /**
   * 403异常处理
   * @param error
   */
  private forbiddenErrorHandle(error) {
    return error
  }

  /**
   * 默认异常处理
   */
  private defaultErrorHandle(error) {
    return error
  }
}
